{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.02228999137878418\n",
      "tensor(-1.0000, grad_fn=<DivBackward0>)\n",
      "tensor(-0.8854, grad_fn=<DivBackward0>)\n",
      "tensor([-0.3534,  0.3197], requires_grad=True)\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import time\n",
    "import matplotlib.pyplot as plt\n",
    "import torch\n",
    "import torch.optim as optim\n",
    "import torch.distributions as td\n",
    "\n",
    "def euler_position_to_T(euler_zyx,pos):\n",
    "    \n",
    "    n=euler_zyx.shape[1]\n",
    "    p=pos\n",
    "    \n",
    "    angle_z=euler_zyx[0,:]\n",
    "    angle_y=euler_zyx[1,:]\n",
    "    angle_x=euler_zyx[2,:]\n",
    "    \n",
    "    cos_x, sin_x = torch.cos(angle_x), torch.sin(angle_x)\n",
    "    cos_y, sin_y = torch.cos(angle_y), torch.sin(angle_y)\n",
    "    cos_z, sin_z = torch.cos(angle_z), torch.sin(angle_z)\n",
    "\n",
    "    # Compute the elements of the rotation matrix\n",
    "    R00 = cos_z * cos_y\n",
    "    R01 = cos_z * sin_y * sin_x - sin_z * cos_x\n",
    "    R02 = cos_z * sin_y * cos_x + sin_z * sin_x\n",
    "    R10 = sin_z * cos_y\n",
    "    R11 = sin_z * sin_y * sin_x + cos_z * cos_x\n",
    "    R12 = sin_z * sin_y * cos_x - cos_z * sin_x\n",
    "    R20 = -sin_y\n",
    "    R21 = cos_y * sin_x\n",
    "    R22 = cos_y * cos_x\n",
    "    T_0 = torch.zeros(n)\n",
    "    T_1 = torch.ones(n)\n",
    "\n",
    "    # Construct the rotation matrix R from the elements\n",
    "    transformationT = torch.stack([torch.stack([R00, R01, R02,p[0,:]]),\n",
    "                                   torch.stack([R10, R11, R12,p[1,:]]),\n",
    "                                   torch.stack([R20, R21, R22,p[2,:]]),\n",
    "                                   torch.stack([T_0, T_0, T_0,T_1])])\n",
    "    \n",
    "    T=torch.transpose(transformationT,0,2)\n",
    "    T=torch.transpose(T,1,2)\n",
    "    \n",
    "    return T\n",
    "\n",
    "def euler_to_rotation_matrix_zyx(angle_z, angle_y, angle_x):\n",
    "    # Extract the individual angles\n",
    "    #angle_z, angle_y, angle_x = euler_angles\n",
    "\n",
    "    # Compute trigonometric functions for the angles\n",
    "    cos_x, sin_x = torch.cos(angle_x), torch.sin(angle_x)\n",
    "    cos_y, sin_y = torch.cos(angle_y), torch.sin(angle_y)\n",
    "    cos_z, sin_z = torch.cos(angle_z), torch.sin(angle_z)\n",
    "\n",
    "    # Compute the elements of the rotation matrix\n",
    "    R00 = cos_z * cos_y\n",
    "    R01 = cos_z * sin_y * sin_x - sin_z * cos_x\n",
    "    R02 = cos_z * sin_y * cos_x + sin_z * sin_x\n",
    "    R10 = sin_z * cos_y\n",
    "    R11 = sin_z * sin_y * sin_x + cos_z * cos_x\n",
    "    R12 = sin_z * sin_y * cos_x - cos_z * sin_x\n",
    "    R20 = -sin_y\n",
    "    R21 = cos_y * sin_x\n",
    "    R22 = cos_y * cos_x\n",
    "\n",
    "    # Construct the rotation matrix R from the elements\n",
    "    rotation_matrix = torch.stack([torch.stack([R00, R01, R02]),\n",
    "                                   torch.stack([R10, R11, R12]),\n",
    "                                   torch.stack([R20, R21, R22])])\n",
    "\n",
    "    return rotation_matrix\n",
    "\n",
    "\n",
    "\n",
    "n_horizon=1\n",
    "angle_z=torch.zeros([n_horizon])\n",
    "angle_y=torch.zeros([n_horizon])\n",
    "angle_x=torch.zeros([n_horizon])\n",
    "\n",
    "\n",
    "euler_to_rotation_matrix_zyx(angle_z,angle_y,angle_x).shape\n",
    "\n",
    "\n",
    "def xyz_to_rangebearing(v):\n",
    "\n",
    "    v_norm=torch.sqrt(torch.sum(v*v,axis=0))\n",
    "    unit_x=v*0.\n",
    "    unit_x[0,:]=1\n",
    "\n",
    "    v_normalized=v/(v_norm.repeat(3,1))\n",
    "\n",
    "    cos_bear=torch.sum(unit_x*v_normalized,axis=0)\n",
    "    \n",
    "    return v_norm,cos_bear\n",
    "    \n",
    "    \n",
    "v=torch.ones([3,666])\n",
    "\n",
    "r,cb=xyz_to_rangebearing(v)\n",
    "bearing=torch.acos(cb)\n",
    "\n",
    "\n",
    "\n",
    "def calculate_visibility(a,bearing):\n",
    "    a_vis=torch.tensor(a)\n",
    "    fov=torch.pi\n",
    "    v=1/(1+torch.exp(-a_vis*torch.cos(bearing*torch.pi/fov)))#*(1+torch.exp(-torch.tensor(a_vis)))\n",
    "    v_max=1/(1+torch.exp(-a_vis))\n",
    "    v_min=1/(1+torch.exp(a_vis))\n",
    "    \n",
    "    v_normalized=(v-v_min)/(v_max-v_min)\n",
    "    return v_normalized\n",
    "\n",
    "\n",
    "vis=calculate_visibility(a=10.0,bearing=bearing)\n",
    "\n",
    "\n",
    "s=torch.tensor([0.0,0.0],requires_grad=True)\n",
    "\n",
    "pts_size=128\n",
    "pts_W=torch.rand([3,pts_size])\n",
    "\n",
    "ud=td.Uniform(-3,3)\n",
    "pts_W[0,:]=2.3\n",
    "pts_W[1,:]=ud.sample([1,pts_size])+1\n",
    "pts_W[2,:]=ud.sample([1,pts_size])+1\n",
    "\n",
    "\n",
    "def loss_function(s):\n",
    "    R=euler_to_rotation_matrix_zyx(angle_z=s[0],angle_y=s[1],angle_x=torch.tensor(0.))\n",
    "\n",
    "    pts_C=R@pts_W\n",
    "    v=pts_C\n",
    "    r,cb=xyz_to_rangebearing(v)\n",
    "    b=torch.acos(cb)\n",
    "    loss1=-calculate_visibility(a=10.0,bearing=b[0])*pts_size\n",
    "    loss2=-torch.sum(calculate_visibility(a=1.0,bearing=b[1:]))\n",
    "    \n",
    "    return loss1,loss2,loss1+loss2\n",
    "    \n",
    "loss_function(s)\n",
    "    \n",
    "    \n",
    "# 创建一个优化器，这里使用梯度下降法\n",
    "optimizer = optim.Adam([s], lr=0.01)\n",
    "\n",
    "loss_list=[]\n",
    "s_list=[]\n",
    "\n",
    "t0=time.time()\n",
    "for i in range(200):\n",
    "    \n",
    "    loss_prev=loss\n",
    "    \n",
    "    optimizer.zero_grad()  # 梯度清零\n",
    "    loss1,loss2,loss = loss_function(s)\n",
    "    loss.backward()  # 反向传播计算梯度\n",
    "    \n",
    "    loss_list.append(loss.item())\n",
    "    s_list.append(s.detach().numpy())\n",
    "\n",
    "    optimizer.step()  # 更新变量\n",
    "    \n",
    "    if torch.abs(loss-loss_prev)<1e-3:\n",
    "        break\n",
    "    \n",
    "    \n",
    " \n",
    "\n",
    "t1=time.time()\n",
    "print(t1-t0)\n",
    "print(loss1/pts_size)\n",
    "print(loss2/pts_size)\n",
    "plt.plot(loss_list)\n",
    "\n",
    "\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.056090354919433594\n",
      "tensor([0.7955, 0.8437, 0.8816, 0.9199, 0.9432, 0.9536, 0.9641, 0.9720, 0.9781,\n",
      "        0.9840, 0.9876, 0.9893, 0.9903, 0.9914, 0.9925, 0.9926, 0.9923, 0.9922,\n",
      "        0.9922, 0.9910], grad_fn=<MeanBackward1>)\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_5535/3683623570.py:104: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
      "  a_vis=torch.tensor(a)\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7fa7374cfa30>,\n",
       " <matplotlib.lines.Line2D at 0x7fa7374cfa60>]"
      ]
     },
     "execution_count": 148,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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ttQE+3LP5dGmtdJUKbxMmjSJF198sdJttm3bRkxMTJULsdnsT1hfe+21PPzwwwB06tSJ5cuXM3Xq1DOGlylTpvD0009X+XgiIiJ1kae7lZahfrQM9Su3/mRrzZ70k72fToWak601mw9ls/lQNp7uVsZf2dKkM6hieJk4cSJjxoypdJvo6OjzKiQ4OBh3d3fatWtXbn3btm1ZtmzZGfebPHkyjzzySNnf2dnZREVFnVcNIiIiddXprTXdmlXUWpNf1lKTV1hi6nxOVQovISEhhISEnH3D8+Dp6Um3bt1ITEwst37Hjh00bdr0jPt5eXnh5eXlkJpERETkZGuNfXoDZ+CwZ16SkpLIyMggKSmJ0tJS4uPjAWjZsiW+vvaTj4mJYcqUKVx33XUAPProo9x4441cdtllXHHFFcyfP585c+bw66+/OqpMERERcTEOCy9PPPEEM2bMKPu7c+fOACxZsoQ+ffoAkJiYSFbWqSedr7vuOqZOncqUKVN48MEHadOmDd988w29evVyVJkiIiLiYjQ9gIiIiJiuKt/fdXPqShEREXFZCi8iIiLiUhReRERExKUovIiIiIhLUXgRERERl6LwIiIiIi5F4UVERERcisKLiIiIuBSFFxEREXEpCi8iIiLiUhw2t5FZTs52kJ2dbXIlIiIicq5Ofm+fy6xFtS685OTkABAVFWVyJSIiIlJVOTk5BAQEVLpNrZuY0WazkZycjJ+fHxaLpVrfOzs7m6ioKA4cOFDrJ32sS+cKdet8da61V106X51r7WMYBjk5OURGRmK1Vv5US61rebFarTRu3Nihx/D396/V/wKdri6dK9St89W51l516Xx1rrXL2VpcTtIDuyIiIuJSFF5ERETEpSi8VIGXlxdPPvkkXl5eZpficHXpXKFuna/OtfaqS+erc63bat0DuyIiIlK7qeVFREREXIrCi4iIiLgUhRcRERFxKQovIiIi4lIUXv7k7bffplmzZnh7exMXF8fq1asr3f6rr74iJiYGb29vYmNj+fHHH2uo0vM3ZcoUunXrhp+fH6GhoQwbNozExMRK95k+fToWi6Xc4u3tXUMVX5innnrqL7XHxMRUuo8rXleAZs2a/eVcLRYL999/f4Xbu9p1/e233xg6dCiRkZFYLBa+++67cq8bhsETTzxBREQE9erVo1+/fuzcufOs71vVz31NqOxci4uLeeyxx4iNjcXHx4fIyEhuu+02kpOTK33P8/ks1ISzXdcxY8b8pe4BAwac9X2d8brC2c+3os+wxWLhpZdeOuN7Ouu1dRSFl9PMmjWLRx55hCeffJL169fTsWNH+vfvT2pqaoXbL1++nJtuuomxY8eyYcMGhg0bxrBhw9i8eXMNV141S5cu5f7772flypUsWLCA4uJirr76avLy8irdz9/fn8OHD5ct+/fvr6GKL1z79u3L1b5s2bIzbuuq1xVgzZo15c5zwYIFAIwYMeKM+7jSdc3Ly6Njx468/fbbFb7+n//8hzfeeIOpU6eyatUqfHx86N+/PwUFBWd8z6p+7mtKZeean5/P+vXrefzxx1m/fj3ffvstiYmJXHPNNWd936p8FmrK2a4rwIABA8rV/b///a/S93TW6wpnP9/Tz/Pw4cN89NFHWCwWrr/++krf1xmvrcMYUqZ79+7G/fffX/Z3aWmpERkZaUyZMqXC7UeOHGkMHjy43Lq4uDjjnnvucWid1S01NdUAjKVLl55xm48//tgICAiouaKq0ZNPPml07NjxnLevLdfVMAzjoYceMlq0aGHYbLYKX3fl6woYs2fPLvvbZrMZ4eHhxksvvVS2LjMz0/Dy8jL+97//nfF9qvq5N8Ofz7Uiq1evNgBj//79Z9ymqp8FM1R0rrfffrtx7bXXVul9XOG6Gsa5Xdtrr73WuPLKKyvdxhWubXVSy8sJRUVFrFu3jn79+pWts1qt9OvXjxUrVlS4z4oVK8ptD9C/f/8zbu+ssrKyAGjYsGGl2+Xm5tK0aVOioqK49tpr2bJlS02UVy127txJZGQk0dHRjB49mqSkpDNuW1uua1FREZ999hl33nlnpZOUuvJ1Pd3evXtJSUkpd+0CAgKIi4s747U7n8+9s8rKysJisRAYGFjpdlX5LDiTX3/9ldDQUNq0acN9993H0aNHz7htbbquR44cYd68eYwdO/as27rqtT0fCi8npKenU1paSlhYWLn1YWFhpKSkVLhPSkpKlbZ3RjabjQkTJnDppZdy0UUXnXG7Nm3a8NFHH/H999/z2WefYbPZ6NmzJwcPHqzBas9PXFwc06dPZ/78+bz77rvs3buX3r17k5OTU+H2teG6Anz33XdkZmYyZsyYM27jytf1z05en6pcu/P53DujgoICHnvsMW666aZKJ+6r6mfBWQwYMIBPPvmERYsW8eKLL7J06VIGDhxIaWlphdvXlusKMGPGDPz8/Bg+fHil27nqtT1ftW5Waama+++/n82bN5/13miPHj3o0aNH2d89e/akbdu2vPfeezzzzDOOLvOCDBw4sOz3Dh06EBcXR9OmTfnyyy/P6f9mXNW0adMYOHAgkZGRZ9zGla+r2BUXFzNy5EgMw+Ddd9+tdFtX/SyMGjWq7PfY2Fg6dOhAixYt+PXXX+nbt6+JlTneRx99xOjRo8/6IL2rXtvzpZaXE4KDg3Fzc+PIkSPl1h85coTw8PAK9wkPD6/S9s5m/PjxzJ07lyVLltC4ceMq7evh4UHnzp3ZtWuXg6pznMDAQFq3bn3G2l39ugLs37+fhQsXctddd1VpP1e+rievT1Wu3fl87p3JyeCyf/9+FixYUGmrS0XO9llwVtHR0QQHB5+xble/rif9/vvvJCYmVvlzDK57bc+VwssJnp6edOnShUWLFpWts9lsLFq0qNz/mZ6uR48e5bYHWLBgwRm3dxaGYTB+/Hhmz57N4sWLad68eZXfo7S0lE2bNhEREeGACh0rNzeX3bt3n7F2V72up/v4448JDQ1l8ODBVdrPla9r8+bNCQ8PL3ftsrOzWbVq1Rmv3fl87p3FyeCyc+dOFi5cSFBQUJXf42yfBWd18OBBjh49esa6Xfm6nm7atGl06dKFjh07VnlfV72258zsJ4adycyZMw0vLy9j+vTpxtatW41x48YZgYGBRkpKimEYhnHrrbcakyZNKtv+jz/+MNzd3Y2XX37Z2LZtm/Hkk08aHh4exqZNm8w6hXNy3333GQEBAcavv/5qHD58uGzJz88v2+bP5/r0008bP//8s7F7925j3bp1xqhRowxvb29jy5YtZpxClUycONH49ddfjb179xp//PGH0a9fPyM4ONhITU01DKP2XNeTSktLjSZNmhiPPfbYX15z9euak5NjbNiwwdiwYYMBGP/973+NDRs2lPWweeGFF4zAwEDj+++/NxISEoxrr73WaN68uXH8+PGy97jyyiuNN998s+zvs33uzVLZuRYVFRnXXHON0bhxYyM+Pr7c57iwsLDsPf58rmf7LJilsnPNyckx/v73vxsrVqww9u7dayxcuNC4+OKLjVatWhkFBQVl7+Eq19Uwzv7vsWEYRlZWllG/fn3j3XffrfA9XOXaOorCy5+8+eabRpMmTQxPT0+je/fuxsqVK8teu/zyy43bb7+93PZffvml0bp1a8PT09No3769MW/evBquuOqACpePP/64bJs/n+uECRPK/rmEhYUZgwYNMtavX1/zxZ+HG2+80YiIiDA8PT2NRo0aGTfeeKOxa9eustdry3U96eeffzYAIzEx8S+vufp1XbJkSYX/7p48J5vNZjz++ONGWFiY4eXlZfTt2/cv/xyaNm1qPPnkk+XWVfa5N0tl57p3794zfo6XLFlS9h5/PtezfRbMUtm55ufnG1dffbUREhJieHh4GE2bNjXuvvvuv4QQV7muhnH2f48NwzDee+89o169ekZmZmaF7+Eq19ZRLIZhGA5t2hERERGpRnrmRURERFyKwouIiIi4FIUXERERcSkKLyIiIuJSFF5ERETEpSi8iIiIiEtReBERERGXovAiIiIiLkXhRURERFyKwouIiIi4FIUXERERcSkKLyIiIuJS/h93jkTm/6toOAAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "dt=0.1\n",
    "n_horizon=20\n",
    "\n",
    "A=torch.tensor([[1.,0.,dt,0.],\n",
    "                [0.,1.,0.,dt],\n",
    "                [0.,0.,1.,0.],\n",
    "                [0.,0.,0.,1.]])\n",
    "\n",
    "\n",
    "B=torch.tensor([[0.,0.],\n",
    "                [0.,0.],\n",
    "                [dt,0.],\n",
    "                [0.,dt]])\n",
    "\n",
    "\n",
    "A=torch.tensor([[1.,0.,0.,0.],\n",
    "                [0.,1.,0.,0.],\n",
    "                [0.,0.,1.,0.],\n",
    "                [0.,0.,0.,1.]])\n",
    "\n",
    "\n",
    "B=torch.tensor([[1.,0.],\n",
    "                [0.,1.],\n",
    "                [0.,0.],\n",
    "                [0.,0.]])\n",
    "\n",
    "\n",
    "def multi_dot(M,n):\n",
    "    # 扩展A为大小为n的三维张量\n",
    "    batch_M = M.unsqueeze(0).expand(n, -1, -1)\n",
    "\n",
    "    # 计算n个A的点积\n",
    "    result = torch.bmm(batch_M, batch_M.transpose(1, 2))\n",
    "    \n",
    "    return result\n",
    "\n",
    "\n",
    "A_ext=A\n",
    "for i in range(1,n_horizon):\n",
    "    A_ext=torch.vstack([A_ext,torch.matrix_power(A,i+1)])\n",
    "    \n",
    "B_ext=torch.zeros([4*n_horizon,2*n_horizon])\n",
    "for r in range(n_horizon):\n",
    "    for c in range(n_horizon):\n",
    "        if r>=c:\n",
    "            B_ext[4*r:4*r+4,2*c:2*c+2]=torch.matrix_power(A,r-c)@B\n",
    "\n",
    "u=torch.zeros([2*n_horizon,1],requires_grad=True)\n",
    "x0=torch.zeros([4,1])\n",
    "x_aug=A_ext@x0+B_ext@u\n",
    "\n",
    "def loss_function(u):\n",
    "\n",
    "    x0=torch.zeros([4,1])\n",
    "    x_aug=A_ext@x0+B_ext@u\n",
    "\n",
    "    x_aug=x_aug.reshape([n_horizon,4]).T\n",
    "    euler_zyx=x_aug[:3,:]\n",
    "    euler_zyx[2,:]=0.\n",
    "\n",
    "\n",
    "    p=torch.zeros([3,n_horizon])\n",
    "    p[1,:]=torch.arange(n_horizon)*1.0\n",
    "    #p[1,:]=torch.arange(n_horizon)\n",
    "\n",
    "    T_C_W=euler_position_to_T(euler_zyx=euler_zyx,pos=p)\n",
    "    T_W_C=torch.inverse(T_C_W)\n",
    "\n",
    "    pc_size=128\n",
    "    pc_W=torch.rand([3,pc_size])*4#+torch.tensor([3.,0.,-30.]).repeat([pc_size,1]).T\n",
    "    \n",
    "    pc_W_aug=torch.vstack([pc_W,torch.ones(pc_size)])\n",
    "    pc_W_aug=pc_W_aug.repeat(n_horizon,1,1)\n",
    "\n",
    "    pc_C_aug=T_W_C@pc_W_aug\n",
    "    \n",
    "    pc_aug=pc_C_aug\n",
    "    pc_norm=torch.sqrt(torch.sum(pc_aug[:,:3,:]*pc_aug[:,:3,:],axis=1)).reshape([n_horizon,1,pc_size])\n",
    "    pc_normalized=pc_aug[:,:3,:]/pc_norm\n",
    "\n",
    "    cos_bear=pc_normalized[:,0,:]\n",
    "\n",
    "    bear=torch.acos(cos_bear)\n",
    "\n",
    "    vis=calculate_visibility(torch.tensor(1.0),bear)\n",
    "\n",
    "    \n",
    "    loss=-torch.mean(vis)+u.T@u*0.01\n",
    "    \n",
    "    \n",
    "    \n",
    "    \n",
    "    return loss,vis\n",
    "\n",
    "t0=time.time()\n",
    "\n",
    "optimizer = optim.Adam([u], lr=0.01)\n",
    "\n",
    "loss_list=[]\n",
    "s_list=[]\n",
    "\n",
    "\n",
    "for i in range(50):\n",
    "    loss_prev=loss\n",
    "    optimizer.zero_grad()  # 梯度清零\n",
    "    loss,vis = loss_function(u)\n",
    "    loss.backward()  # 反向传播计算梯度\n",
    "    #print(loss)\n",
    "    loss_list.append(loss.item())\n",
    "    s_list.append(s.detach().numpy())\n",
    "    #print(loss)\n",
    "    \n",
    "    if i>5:\n",
    "        optimizer = optim.Adam([u], lr=0.01)\n",
    "\n",
    "    \n",
    "    if torch.abs(loss_prev-loss)<1e-33:\n",
    "        break\n",
    "    \n",
    "    \n",
    "    if i%1==0:\n",
    "        optimizer.step()  # 更新变量\n",
    "\n",
    "t1=time.time()\n",
    "print(t1-t0)    \n",
    "\n",
    "print(torch.mean(vis,axis=1))\n",
    "\n",
    "plt.plot(loss_list)\n",
    "plt.show()\n",
    "x=A_ext@x0+B_ext@u\n",
    "x=x.reshape([n_horizon,4]).T[:2,:]\n",
    "plt.plot(x.detach().numpy().T)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.6762, 0.4177, 0.7506, 0.7455, 0.2279, 0.3196, 0.3213, 0.4694, 0.0212,\n",
      "         0.9142, 0.2476, 0.1396, 0.0738, 0.5923, 0.7682, 0.2749, 0.1511, 0.5796,\n",
      "         0.1555, 0.6778, 0.3175, 0.5486, 0.6308, 0.2066, 0.0542, 0.1430, 0.9190,\n",
      "         0.2816, 0.6676, 0.0512, 0.0991, 0.4407, 0.6664, 0.5074, 0.7352, 0.3134,\n",
      "         0.6988, 0.7392, 0.8274, 0.1160, 0.8130, 0.0887, 0.6256, 0.8970, 0.2866,\n",
      "         0.4728, 0.0826, 0.5024, 0.4414, 0.2150, 0.2200, 0.8418, 0.0439, 0.4100,\n",
      "         0.6458, 0.2815, 0.1929, 0.2597, 0.1688, 0.6566, 0.2864, 0.4085, 0.1147,\n",
      "         0.9657, 0.3376, 0.0903, 0.1270, 0.4937, 0.3567, 0.0056, 0.9125, 0.1710,\n",
      "         0.2680, 0.2544, 0.9515, 0.2190, 0.1117, 0.6485, 0.2560, 0.4325]])\n",
      "tensor([[0.6762, 0.4177, 0.0000, 0.0000, 0.2279, 0.3196, 0.0000, 0.0000, 0.0212,\n",
      "         0.9142, 0.0000, 0.0000, 0.0738, 0.5923, 0.0000, 0.0000, 0.1511, 0.5796,\n",
      "         0.0000, 0.0000, 0.3175, 0.5486, 0.0000, 0.0000, 0.0542, 0.1430, 0.0000,\n",
      "         0.0000, 0.6676, 0.0512, 0.0000, 0.0000, 0.6664, 0.5074, 0.0000, 0.0000,\n",
      "         0.6988, 0.7392, 0.0000, 0.0000, 0.8130, 0.0887, 0.0000, 0.0000, 0.2866,\n",
      "         0.4728, 0.0000, 0.0000, 0.4414, 0.2150, 0.0000, 0.0000, 0.0439, 0.4100,\n",
      "         0.0000, 0.0000, 0.1929, 0.2597, 0.0000, 0.0000, 0.2864, 0.4085, 0.0000,\n",
      "         0.0000, 0.3376, 0.0903, 0.0000, 0.0000, 0.3567, 0.0056, 0.0000, 0.0000,\n",
      "         0.2680, 0.2544, 0.0000, 0.0000, 0.1117, 0.6485, 0.0000, 0.0000]])\n"
     ]
    }
   ],
   "source": [
    "#print(u.T)\n",
    "\n",
    "x=A_ext@x0+B_ext@u\n",
    "\n",
    "torch.pinverse(B_ext)@(x-A_ext@x0)\n",
    "\n",
    "x=torch.rand([80,1])\n",
    "print(x.T)\n",
    "u=torch.pinverse(B_ext)@(x-A_ext@x0)\n",
    "\n",
    "x=A_ext@x0+B_ext@u\n",
    "print(x.T)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "ename": "RuntimeError",
     "evalue": "Expected size for first two dimensions of batch2 tensor to be: [3, 2560] but got: [3, 3].",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mRuntimeError\u001b[0m                              Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[10], line 34\u001b[0m\n\u001b[1;32m     30\u001b[0m I_aug\u001b[39m=\u001b[39mtorch\u001b[39m.\u001b[39meye(\u001b[39m3\u001b[39m)\u001b[39m.\u001b[39mrepeat(V\u001b[39m.\u001b[39mshape[\u001b[39m2\u001b[39m],\u001b[39m1\u001b[39m,\u001b[39m1\u001b[39m)\n\u001b[1;32m     31\u001b[0m I_aug\u001b[39m=\u001b[39mtorch\u001b[39m.\u001b[39mtranspose(I_aug,\u001b[39m0\u001b[39m,\u001b[39m2\u001b[39m)\n\u001b[0;32m---> 34\u001b[0m R\u001b[39m=\u001b[39mI_aug\u001b[39m+\u001b[39mV\u001b[39m+\u001b[39mV\u001b[39m@V\u001b[39;49m\u001b[39m*\u001b[39m((\u001b[39m1\u001b[39m\u001b[39m-\u001b[39mdot)\u001b[39m/\u001b[39mtorch\u001b[39m.\u001b[39msum(crs\u001b[39m*\u001b[39mcrs,axis\u001b[39m=\u001b[39m\u001b[39m0\u001b[39m))\n",
      "\u001b[0;31mRuntimeError\u001b[0m: Expected size for first two dimensions of batch2 tensor to be: [3, 2560] but got: [3, 3]."
     ]
    }
   ],
   "source": [
    "pc_size=128\n",
    "pc_W=torch.rand([3,pc_size])*0+torch.tensor([1.,-20.01,-1.01]).repeat([pc_size,1]).T\n",
    "pc_W_aug=torch.vstack([pc_W,torch.ones(pc_size)])\n",
    "pc_W_aug=pc_W_aug.repeat(n_horizon,1,1)\n",
    "\n",
    "pc_C_aug=pc_W_aug\n",
    "\n",
    "pc_aug=pc_C_aug\n",
    "pc_norm=torch.sqrt(torch.sum(pc_aug[:,:3,:]*pc_aug[:,:3,:],axis=1)).reshape([n_horizon,1,pc_size])\n",
    "pc_normalized=pc_aug[:,:3,:]/pc_norm\n",
    "\n",
    "pc_normalized.shape\n",
    "v_normalized=pc_normalized.reshape([3,-1])\n",
    "\n",
    "unit_x_ext=torch.tensor([1,0,0]).repeat(v_normalized.shape[1],1)\n",
    "\n",
    "\n",
    "\n",
    "crs=v_normalized*0.\n",
    "crs[1,:]=-v_normalized[2]\n",
    "crs[2,:]=v_normalized[1]\n",
    "\n",
    "dot=v_normalized*0.\n",
    "dot=v_normalized[0,:]\n",
    "\n",
    "V=torch.stack([torch.stack([crs[0,:]*0,-crs[2,:],crs[1,:]]),\n",
    "               torch.stack([crs[2,:],crs[1,:]*0,-crs[0,:]]),\n",
    "               torch.stack([-crs[1,:],crs[0,:],crs[2,:]*0])])\n",
    "\n",
    "I_aug=torch.eye(3).repeat(V.shape[2],1,1)\n",
    "I_aug=torch.transpose(I_aug,0,2)\n",
    "\n",
    "\n",
    "R=I_aug+V+V@V*((1-dot)/torch.sum(crs*crs,axis=0))\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([-0.7646, -0.7626, -0.4663, -0.0220, -0.5520, -0.5230, -0.2741, -0.5196,\n",
       "        -0.2212, -0.7822, -0.0124, -0.1465, -0.7456, -0.1664, -0.4609, -0.2914,\n",
       "        -0.7500, -0.7665, -0.6349, -0.4681, -0.6653, -0.6213, -0.7205, -0.7412,\n",
       "        -0.0677, -0.5435, -0.7847, -0.5592, -0.2480, -0.4791, -0.7831, -0.7451,\n",
       "        -0.6399, -0.6359, -0.6178, -0.7036, -0.4918, -0.7716, -0.0677, -0.7233,\n",
       "        -0.5620, -0.4815, -0.5188, -0.4218, -0.1085, -0.7389, -0.5315, -0.4636,\n",
       "        -0.5582, -0.1733, -0.7846, -0.6338, -0.7667, -0.1380, -0.6299, -0.7728,\n",
       "        -0.1248, -0.6589, -0.1136, -0.7544, -0.7844, -0.7453, -0.4462, -0.5904,\n",
       "        -0.3628, -0.5190, -0.6385, -0.6941, -0.6270, -0.6043, -0.7853, -0.7607,\n",
       "        -0.7744, -0.6012, -0.6693, -0.7778, -0.6721, -0.4480, -0.7066, -0.5392,\n",
       "        -0.1475, -0.7373, -0.3255, -0.7512, -0.7835, -0.6198, -0.4330, -0.6806,\n",
       "        -0.5322, -0.2292, -0.5927, -0.6943, -0.4465, -0.2848, -0.5759, -0.7312,\n",
       "        -0.7848, -0.3032, -0.5290, -0.6476, -0.6835, -0.4452, -0.6024, -0.4930,\n",
       "        -0.3463, -0.7467, -0.6241, -0.5926, -0.5644, -0.5169, -0.7131, -0.2787,\n",
       "        -0.7305, -0.6838, -0.6002, -0.3099, -0.6159, -0.1503, -0.5831, -0.6671,\n",
       "        -0.6461, -0.6030, -0.1461, -0.6900, -0.5192, -0.5768, -0.3899, -0.6546])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "pc=torch.rand([3,128])\n",
    "\n",
    "v=pc\n",
    "\n",
    "cy=torch.sqrt(v[0,:]**2+v[1,:]**2)\n",
    "\n",
    "theta_z=torch.atan2(v[1,:],v[0,:])\n",
    "theta_y=torch.atan2(-v[2,:],torch.sqrt(v[1,:]**2+v[2,:]**2))\n",
    "\n",
    "theta_y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "metadata": {},
   "outputs": [
    {
     "ename": "IndexError",
     "evalue": "too many indices for tensor of dimension 2",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mIndexError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[143], line 5\u001b[0m\n\u001b[1;32m      1\u001b[0m pc_aug\u001b[39m=\u001b[39mtorch\u001b[39m.\u001b[39mrand([\u001b[39m3\u001b[39m,\u001b[39m128\u001b[39m])\n\u001b[0;32m----> 5\u001b[0m pc_norm\u001b[39m=\u001b[39mtorch\u001b[39m.\u001b[39msqrt(torch\u001b[39m.\u001b[39msum(pc_aug[:,:\u001b[39m3\u001b[39;49m,:]\u001b[39m*\u001b[39mpc_aug[:,:\u001b[39m3\u001b[39m,:],axis\u001b[39m=\u001b[39m\u001b[39m1\u001b[39m))\u001b[39m.\u001b[39mreshape([\u001b[39m5\u001b[39m,\u001b[39m1\u001b[39m,\u001b[39m128\u001b[39m])\n\u001b[1;32m      6\u001b[0m pc_normalized\u001b[39m=\u001b[39mpc_aug[:,:\u001b[39m3\u001b[39m,:]\u001b[39m/\u001b[39mpc_norm\n\u001b[1;32m      8\u001b[0m cos_bear\u001b[39m=\u001b[39mpc_normalized[:,\u001b[39m0\u001b[39m,:]\n",
      "\u001b[0;31mIndexError\u001b[0m: too many indices for tensor of dimension 2"
     ]
    }
   ],
   "source": [
    "pc_aug=torch.rand([3,128])\n",
    "\n",
    "\n",
    "\n",
    "pc_norm=torch.sqrt(torch.sum(pc_aug[:,:3,:]*pc_aug[:,:3,:],axis=1)).reshape([5,1,128])\n",
    "pc_normalized=pc_aug[:,:3,:]/pc_norm\n",
    "\n",
    "cos_bear=pc_normalized[:,0,:]\n",
    "\n",
    "bear=torch.acos(cos_bear)\n",
    "\n",
    "vis=calculate_visibility(torch.tensor(1.0),bear)\n",
    "\n",
    "vis.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.5707963264615632"
      ]
     },
     "execution_count": 147,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.arctan2(3.0,1e-9)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
